// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Odbc;
using System.Linq;
using System.Text;
using JetBrains.Annotations;

namespace SnapObjects.Data.Odbc
{
    internal class OdbcAseAdoDbProvider : AdoDbProvider
    {
        public OdbcAseAdoDbProvider(DataContext dataContext) : base(dataContext)
        {
        }

        protected override IAdoDbResultSet<TModel> CreateResultSet<TModel>(
            IDbCommand command,
            IDataReader reader,
            IEnumerable<IAdoDbParameter> parameters)
        {
            var visitor = new OdbcAseAdoDbDataVisitor(
                (OdbcCommand)command, (OdbcDataReader)reader, parameters, _dataContext.ContextOptions);

            var mapper = new OdbcAseTypeMapper(_dataContext.ContextOptions);

            return new OdbcAseAdoDbResultSet<TModel>(visitor, mapper);
        }

        protected override IAdoDbDataVisitor CreateDataVisitor(
            IDbCommand command,
            IDataReader reader,
            IEnumerable<IAdoDbParameter> parameters)
        {
            return new OdbcAseAdoDbDataVisitor(
                (OdbcCommand)command, (OdbcDataReader)reader, parameters, _dataContext.ContextOptions);
        }

        protected override IAdoDbCommand CreateAdoDbCommand(
            [NotNull] string sqlText,
            IEnumerable<IAdoDbParameter> parameters,
            CommandType commandType = CommandType.Text,
            bool addExceptionToTransaction = true)
        {
            return new OdbcAseAdoDbCommand(sqlText, parameters, addExceptionToTransaction, commandType);
        }

        public override string GenerateSqlProcedureLiteral(string sql,
            ref IEnumerable<IAdoDbParameter> parameters)
        {
            // eg: "call " + sql + " (?, ?)"
            if (parameters.Count() < 1)
            {
                return "{" + "call " + sql + "}";
            }

            IList<IAdoDbParameter> tempParameters = new List<IAdoDbParameter>();

            var sqlBuilder = new StringBuilder("call " + sql + " (");

            bool appendComma = false;

            foreach (var parameter in parameters)
            {
                if (parameter.Direction == ParameterDirection.ReturnValue)
                {
                    sqlBuilder.Insert(0, "?=");

                    tempParameters.Insert(0, parameter);
                }
                else
                {
                    if (appendComma)
                    {
                        sqlBuilder.Append(",");
                    }

                    sqlBuilder.Append(" ? ");

                    tempParameters.Add(parameter);

                    appendComma = true;
                }
            }

            parameters = tempParameters;

            sql = sqlBuilder.Append(")").ToString();

            return "{" + sql + "}";
        }
    }
}
